package com.sky.service.impl;

import com.fasterxml.jackson.databind.util.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        // 对前端 传来的明文密码，进行了md5 加密处理

//        password = DigestUtils.md5DigestAsHex(password.getBytes());
        // 上面这行代码就是进行加密的,先注释掉,因为数据库还没有加密,仅仅只是java代码加密的话,
        // 就和数据库的明文密码不匹配,就会导致登录不成功,所以 等之后 注册用户的时候,也将数据库的密码进行加密之后再放开这行代码

        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }


    // 新增员工的实现类


    @Override
    public void save(EmployeeDTO employeeDTO) {

        // 虽然我们用dto来进行封装，但是mapper 层调用的话肯定还是用实体类，所以需要将dto转换为实体类

        // 将实体类Employee 先 new出来

        Employee employee = new Employee();

        // 对象的属性拷贝,切记位置不要搞错了，是dto 拷贝到实体类，所以是 先 employeeDTO,后 employee 的顺序

        // BeanUtils 是自带的工具类 ，切记对象的属性拷贝一定是属性名要一致，不要写错了

        // 但是dto 中的属性是不全的，所以没有办法拷贝为一个完整实体类，所以dto中没有的属性需要手动添加

        BeanUtils.copyProperties(employeeDTO,employee);

        // 手动设置 账号的状态,1表示正常，0 表示锁定， StatusConstant.ENABLE 是一个设置的公共的常量

        employee.setStatus(StatusConstant.ENABLE);

        // 手动设置密码，默认 密码 123456,需要 MD5 加密

//        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));  这里的123456 也需要设置为常量
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

        // 手动设置 当前创建时间和修改时间

        employee.setCreateTime(LocalDateTime.now());

        employee.setUpdateTime(LocalDateTime.now());

        //  手动设置当前记录创建人的id 和 修改人的id,并且动态的取出了当前登录用户的id

        employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());


        // 开始service 调用mapper层 参数为实体类，注意参数的传递

        employeeMapper.insert(employee);

    }


    // 员工的分页查询

    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {

        // select * from employee limit 0,10  这个是mysql 的分页语句

        // 这里直接使用pageHelper 插件

        // 开始分页，调用pageHelper中方法 通过dto 告诉pageHelper 需要传递的页数 和 页码  getPage 页码  getPageSize 页数
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

        // 调用mapper 进行 方法的实现 这里的话就是传递dto ，而不是直接传递实体类 ，因为dto里面包含所需要返回的参数

        // pageHelper 要求我们的返回值是固定的，Page<实体类>

       Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

        //用pageHelper 固定的 返回 值 page 来获取 PageResult 中 的 total  和 records

         long total = page.getTotal();
         List<Employee> records = page.getResult();
         // 返回 PageResutl 中的 total 和 records
        return new PageResult(total,records);
    }


    // 启用和禁用员工的账号

    @Override
    public void starOrStop(Integer status, Long id) {

        // 启用和禁用本质就是修改 这张表的status ，并且通过 id 来修改

        // sql 语句为 update employee set status = ? where id =?

        // 传参的话是传递实体类 中 的 status 字段 和 id 字段

        // 创建实体类

        Employee employee = new Employee();

        // 赋值 stauts （状态） 和 id （主键）

        employee.setStatus(status);

        employee.setId(id);

        employeeMapper.update(employee);


    }


    // 通过id 来查询员工的 信息
    @Override
    public Employee getById(Long id) {

        // 调用mappper层 并且将密码简单设置一下，不让前端看见

       Employee employee =  employeeMapper.getById(id);

       employee.setPassword("****");
        return employee;
    }

    // 修改员工的信息

    @Override
    public void update(EmployeeDTO employeeDTO) {

        // 因为之前提供了一个update方法 里面可以修改这张员工表的所有字段

        // 但是 切记，这个update 方法 是针对于 实体类的，这里是dto类

        // 所以需要用对象的属性拷贝，进行数据的转换

        // 创建实体类

        Employee employee = new Employee();

        // 对象的属性拷贝

        BeanUtils.copyProperties(employeeDTO,employee);

        // 因为dto中是没有 修改人和修改时间的，所以需要手动添加属性

        // 添加修改人
        employee.setUpdateUser(BaseContext.getCurrentId());

        // 添加修改人时间信息
        employee.setUpdateTime(LocalDateTime.now());

        // 调用公用的update 方法

        employeeMapper.update(employee);

    }


}
















